// src/utils/token-utils.js
/**
 * Token 加密工具类 - 使用系统环境变量
 */
class TokenUtils {
  static #algorithm = {
    name: 'AES-GCM',
    length: 256
  };

  // 从系统环境变量获取加密密钥
  static async #getEncryptionKey() {
    try {
      // 方法1: 从构建时注入的环境变量读取
      const systemKey = typeof __FRONTEND_ENCRYPTION_KEY__ !== 'undefined' 
        ? __FRONTEND_ENCRYPTION_KEY__ 
        : null;

      if (systemKey) {
        console.log('使用系统环境变量加密密钥');
        const keyData = new TextEncoder().encode(systemKey.slice(0, 32));
        return await crypto.subtle.importKey(
          'raw',
          keyData,
          this.#algorithm,
          false,
          ['encrypt', 'decrypt']
        );
      }

      // 方法2: 降级到基于用户信息的密钥
      console.warn('未找到系统加密密钥，使用用户派生密钥');
      return await this.#getUserBasedKey();
      
    } catch (error) {
      console.error('获取加密密钥失败:', error);
      throw new Error('加密服务初始化失败');
    }
  }

  // 基于用户信息生成密钥（降级方案）
  static async #getUserBasedKey() {
    const username = localStorage.getItem('current_user') || 'default_user';
    const loginTime = localStorage.getItem('login_time') || 'default_time';
    
    // 使用固定盐值 + 用户信息生成密钥
    const salt = "DataDictSystemUserSalt2024!";
    const keyMaterial = `${salt}|${username}|${loginTime}`;
    const data = new TextEncoder().encode(keyMaterial);
    const hash = await crypto.subtle.digest('SHA-256', data);
    
    return await crypto.subtle.importKey(
      'raw',
      hash,
      this.#algorithm,
      false,
      ['encrypt', 'decrypt']
    );
  }

  /**
   * 加密 Token
   */
  static async encryptToken(token) {
    try {
      const key = await this.#getEncryptionKey();
      const encoder = new TextEncoder();
      const data = encoder.encode(token);
      
      const iv = crypto.getRandomValues(new Uint8Array(12));
      
      const encrypted = await crypto.subtle.encrypt(
        {
          name: 'AES-GCM',
          iv: iv
        },
        key,
        data
      );

      // 组合: IV + 加密数据
      const result = new Uint8Array(iv.length + encrypted.byteLength);
      result.set(iv, 0);
      result.set(new Uint8Array(encrypted), iv.length);
      
      const encryptedBase64 = btoa(String.fromCharCode(...result));
      
      // 开发环境日志
      if (import.meta.env.DEV) {
        console.log('Token 加密完成', {
          originalLength: token.length,
          encryptedLength: encryptedBase64.length,
          keySource: await this.#getKeySource()
        });
      }
      
      return encryptedBase64;
    } catch (error) {
      console.error('Token 加密失败:', error);
      // 降级处理
      return btoa(unescape(encodeURIComponent(token)));
    }
  }

  /**
   * 获取密钥来源信息（用于调试）
   */
  static async #getKeySource() {
    if (typeof __FRONTEND_ENCRYPTION_KEY__ !== 'undefined') {
      return 'system_env';
    }
    return 'user_derived';
  }

  /**
   * 安全存储加密的 Token
   */
  static async setToken(token, username) {
    try {
      // 存储用户信息（用于密钥生成）
      localStorage.setItem('current_user', username);
      localStorage.setItem('login_time', Date.now().toString());
      
      const encryptedToken = await this.encryptToken(token);
      localStorage.setItem('encrypted_token', encryptedToken);
      
      // 记录密钥来源
      const keySource = await this.#getKeySource();
      localStorage.setItem('encryption_key_source', keySource);
      
      console.log(`Token 加密存储完成 (密钥来源: ${keySource})`);
      return true;
    } catch (error) {
      console.error('存储加密 Token 失败:', error);
      // 降级方案：存储原始 token
      localStorage.setItem('token', token);
      localStorage.setItem('encryption_key_source', 'plain_fallback');
      return false;
    }
  }

  /**
   * 获取并解密 Token
   */
  static async getToken() {
    try {
      const encryptedToken = localStorage.getItem('encrypted_token');
      if (!encryptedToken) {
        return localStorage.getItem('token'); // 降级到普通 token
      }

      const key = await this.#getEncryptionKey();
      
      // 解码 base64
      const encryptedData = Uint8Array.from(atob(encryptedToken), c => c.charCodeAt(0));
      
      // 提取 IV (前12字节) 和加密数据
      const iv = encryptedData.slice(0, 12);
      const data = encryptedData.slice(12);
      
      const decrypted = await crypto.subtle.decrypt(
        {
          name: 'AES-GCM',
          iv: iv
        },
        key,
        data
      );

      const decoder = new TextDecoder();
      const token = decoder.decode(decrypted);
      
      if (import.meta.env.DEV) {
        const keySource = localStorage.getItem('encryption_key_source') || 'unknown';
        console.log('Token 解密完成', { keySource });
      }
      
      return token;
    } catch (error) {
      console.error('Token 解密失败:', error);
      // 降级到普通 token
      return localStorage.getItem('token');
    }
  }

  /**
   * 检查是否有有效的 Token
   */
  static async hasValidToken() {
    try {
      const token = await this.getToken();
      return !!token && token !== 'null' && token !== 'undefined';
    } catch (error) {
      console.error('检查 Token 有效性失败:', error);
      return false;
    }
  }

  /**
   * 获取加密状态信息（用于调试）
   */
  static getEncryptionStatus() {
    const hasEncryptedToken = !!localStorage.getItem('encrypted_token');
    const keySource = localStorage.getItem('encryption_key_source');
    const username = localStorage.getItem('current_user');
    
    return {
      isEncrypted: hasEncryptedToken,
      keySource: keySource || 'unknown',
      username: username || 'unknown',
      hasSystemKey: typeof __FRONTEND_ENCRYPTION_KEY__ !== 'undefined'
    };
  }

  /**
   * 清除所有 Token 数据
   */
  static clearToken() {
    localStorage.removeItem('encrypted_token');
    localStorage.removeItem('token');
    localStorage.removeItem('current_user');
    localStorage.removeItem('login_time');
    localStorage.removeItem('encryption_key_source');
  }
}

export default TokenUtils;